/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.rdf.model.test;

import java.util.List;

import org.apache.jena.rdf.model.*;
import org.apache.jena.rdf.model.test.helpers.ModelHelper;
import org.apache.jena.rdf.model.test.helpers.TestingModelFactory;
import org.apache.jena.vocabulary.RDF;
import org.junit.Assert;

public class TestSimpleListStatements extends AbstractModelTestBase {

    static boolean booleanValue = true;

    static char charValue = 'c';
    static long longValue = 456;
    static float floatValue = 5.67F;
    static double doubleValue = 6.78;
    static String stringValue = "stringValue";
    static String langValue = "en";

    public TestSimpleListStatements(final TestingModelFactory modelFactory, final String name) {
        super(modelFactory, name);
    }

    public void checkReturns(final String things, final StmtIterator it) {
        final Model wanted = ModelHelper.modelWithStatements(this, things);
        final Model got = modelWithStatements(it);
        if ( wanted.isIsomorphicWith(got) == false ) {
            Assert.fail("wanted " + wanted + " got " + got);
        }
    }

    public Model modelWithStatements(final StmtIterator it) {
        final Model m = createModel();
        while (it.hasNext()) {
            m.add(it.nextStatement());
        }
        return m;
    }

    @Override
    public void setUp() {

        super.setUp();
        model.createResource("http://example.org/boolean").addLiteral(RDF.value, TestSimpleListStatements.booleanValue);
        model.createResource("http://example.org/char").addLiteral(RDF.value, TestSimpleListStatements.charValue);
        model.createResource("http://example.org/long").addLiteral(RDF.value, TestSimpleListStatements.longValue);
        model.createResource("http://example.org/float").addLiteral(RDF.value, TestSimpleListStatements.floatValue);
        model.createResource("http://example.org/double").addLiteral(RDF.value, TestSimpleListStatements.doubleValue);
        model.createResource("http://example.org/string").addProperty(RDF.value, TestSimpleListStatements.stringValue);
        model.createResource("http://example.org/langString").addProperty(RDF.value, TestSimpleListStatements.stringValue,
                                                                          TestSimpleListStatements.langValue);

    }

    public void testAll() {
        final StmtIterator iter = model.listStatements(null, null, (RDFNode)null);
        int i = 0;
        while (iter.hasNext()) {
            i++;
            iter.next();
        }
        Assert.assertEquals(7, i);
    }

    public void testAllString() {
        final StmtIterator iter = model.listStatements(null, null, (String)null);
        int i = 0;
        while (iter.hasNext()) {
            i++;
            iter.next();
        }
        Assert.assertEquals(7, i);
    }

    public void testBoolean() {
        final List<Statement> got = model.listLiteralStatements(null, null, TestSimpleListStatements.booleanValue).toList();
        Assert.assertEquals(1, got.size());
        final Statement it = got.get(0);
        Assert.assertEquals(ModelHelper.resource("http://example.org/boolean"), it.getSubject());
        Assert.assertEquals(model.createTypedLiteral(TestSimpleListStatements.booleanValue), it.getObject());
    }

    public void testChar() {
        final List<Statement> got = model.listLiteralStatements(null, null, TestSimpleListStatements.charValue).toList();
        Assert.assertEquals(1, got.size());
        final Statement it = got.get(0);
        Assert.assertEquals(ModelHelper.resource("http://example.org/char"), it.getSubject());
        Assert.assertEquals(model.createTypedLiteral(TestSimpleListStatements.charValue), it.getObject());
    }

    public void testDouble() {
        final List<Statement> got = model.listLiteralStatements(null, null, TestSimpleListStatements.doubleValue).toList();
        Assert.assertEquals(1, got.size());
        final Statement it = got.get(0);
        Assert.assertEquals(ModelHelper.resource("http://example.org/double"), it.getSubject());
        Assert.assertEquals(model.createTypedLiteral(TestSimpleListStatements.doubleValue), it.getObject());
    }

    public void testFloat() {
        final List<Statement> got = model.listLiteralStatements(null, null, TestSimpleListStatements.floatValue).toList();
        Assert.assertEquals(1, got.size());
        final Statement it = got.get(0);
        Assert.assertEquals(ModelHelper.resource("http://example.org/float"), it.getSubject());
        Assert.assertEquals(model.createTypedLiteral(TestSimpleListStatements.floatValue), it.getObject());
    }

    public void testLangString() {
        final StmtIterator iter = model.listStatements(null, null, TestSimpleListStatements.stringValue,
                                                       TestSimpleListStatements.langValue);
        int i = 0;
        while (iter.hasNext()) {
            i++;
            Assert.assertEquals(iter.nextStatement().getSubject().getURI(), "http://example.org/langString");
        }
        Assert.assertEquals(1, i);
    }

    public void testListStatementsSPO() {

        final Resource A = ModelHelper.resource(model, "A"), X = ModelHelper.resource(model, "X");
        final Property P = ModelHelper.property(model, "P"), P1 = ModelHelper.property(model, "P1");
        final RDFNode O = ModelHelper.resource(model, "O"), Y = ModelHelper.resource(model, "Y");
        final String S1 = "S P O; S1 P O; S2 P O";
        final String S2 = "A P1 B; A P1 B; A P1 C";
        final String S3 = "X P1 Y; X P2 Y; X P3 Y";
        ModelHelper.modelAdd(model, S1);
        ModelHelper.modelAdd(model, S2);
        ModelHelper.modelAdd(model, S3);
        checkReturns(S1, model.listStatements(null, P, O));
        checkReturns(S2, model.listStatements(A, P1, (RDFNode)null));
        checkReturns(S3, model.listStatements(X, null, Y));
    }

    public void testLong() {
        final List<Statement> got = model.listLiteralStatements(null, null, TestSimpleListStatements.longValue).toList();
        Assert.assertEquals(1, got.size());
        final Statement it = got.get(0);
        Assert.assertEquals(ModelHelper.resource("http://example.org/long"), it.getSubject());
        Assert.assertEquals(model.createTypedLiteral(TestSimpleListStatements.longValue), it.getObject());
    }

    public void testString() {
        final StmtIterator iter = model.listStatements(null, null, TestSimpleListStatements.stringValue);
        int i = 0;
        while (iter.hasNext()) {
            i++;
            Assert.assertEquals(iter.nextStatement().getSubject().getURI(), "http://example.org/string");
        }
        Assert.assertEquals(1, i);
    }
}
